'''
Авторские права принадлежат Алифатову Дмитрию Сергеевичу <dmitry@alifatov.ru>

Вы можете использовать данное Программное обеспечение на любом количестве компьютеров.

Не разрешается распространять Программное обеспечение, извлекать его компоненты и создавать производные работы на его основе.
'''
import sys
import os
import subprocess
from subprocess import *
import fileinput
import socket
import fcntl
import struct
import npyscreen
import time
import pexpect
import re

class Astra_Update():
    astra_build = None
    astra_repo_type = None

    def __int__(self):
        pass

    def system_call(self, command):
        bash_script = ["bash", "-c"]
        bash_script.append(command)
        p = subprocess.run(bash_script, capture_output=True, text=True)
        return p.stdout

    def astra_strict_version(self, ver):
        strict_ver = ['00000000', '00000000', '00000000', '00000000', '00000000']
        index = 0
        for item in ver.split('.'):
            strict_ver[index] = strict_ver[index][:len(strict_ver[index]) - len(item)] + str(item)
            index += 1
        return strict_ver

    def get_astra_build(self):
        """
        возвращает текущую версию Astra Linux
        ['1.7.0.18', '1.7.1.8', '1.7.2.5', '1.7.2.11', '1.7.3.7', '1.7.3.10', '1.7.3.13', '1.7.4.7']
        """
        try:
            f = open('/etc/astra/build_version', 'r')
            astra_version = f.read()
        except:
            return None
        finally:
            f.close()
        return astra_version[:-1]

    def get_repo_level(self):
        apt_cache_policy = self.apt_cache_policy()
        repo_level = 0
        for repo in apt_cache_policy:
            if '-base' in repo['v']:
                repo_level = 1
            elif '.ext' in repo['v']:
                repo_level = 2
                break
        return repo_level

    def upgradable_packages(self):
        #apt_list = iter(self.system_call('apt list --upgradable -a').split('\n'))
        updates = 0
        pattern = r"^([a-z0-0_.-]+)/*"
        packet = re.compile(pattern, re.I | re.S)
        for line in self.system_call('apt list --upgradable').split('\n'):
            if packet.search(line):
                updates += 1
        return updates

    def apt_cache_policy(self):
        repo = {'priority': 0,
                'link': '',
                'v': '',
                'o': '',
                'a': '',
                'n': '',
                'c': '',
                'b': '',
                }
        cache = iter(self.system_call('apt-cache policy').split("\n"))
        while next(cache).strip() != 'release a=now':
            pass
        repos = []
        for first_line in cache:
            if first_line[0:4].strip().isdigit():
                repos.append(repo.copy())
                repos[-1]['priority'] = int(first_line[0:4].strip())
                repos[-1]['link'] = first_line[5:].split()[0]
                try:
                    second_line = next(cache)
                    if second_line.strip().startswith('release'):
                        for entry in second_line.split(','):
                            if 'v=' in entry:
                                repos[-1]['v'] = entry.split('=')[1]
                            if 'o=' in entry:
                                repos[-1]['o'] = entry.split('=')[1]
                            if 'a=' in entry:
                                repos[-1]['a'] = entry.split('=')[1]
                            if 'n=' in entry:
                                repos[-1]['n'] = entry.split('=')[1]
                            if 'c=' in entry:
                                repos[-1]['c'] = entry.split('=')[1]
                            if 'b=' in entry:
                                repos[-1]['b'] = entry.split('=')[1]
                except:
                    pass
        return repos

class Frame_System_Call(npyscreen.FullScreenPopup):

    def __init__(self, command, pause=True):
        self.command = command
        self.pause = pause
        self.exit = False
        super().__init__()


    def create(self):
        command = self.command
        while len(command) > self.max_x - 6:
            line = command[:self.max_x - 6]
            command = command[self.max_x -6:]
            self.add_widget(npyscreen.FixedText, value=line, editable=False)
        else:
            self.add_widget(npyscreen.FixedText, value=command, editable=False)
            self.add_widget(npyscreen.FixedText, value="-"*(self.max_x - 6), editable=False)

        self.widget_pager = self.add_widget(npyscreen.BufferPager)
        child = pexpect.spawn(self.command, encoding='utf-8')
        line = ""
        try:
            while child.isalive():
                buff = child.read_nonblocking(size=1, timeout=None)
                for char in buff:
                    if char != '\n':
                        line += char
                        if "[Д/н]" in line:
                            self.widget_pager.buffer([line])
                            self.display()
                            time.sleep(2)
                            child.write("Д\n\r")
                            time.sleep(2)
                    else:
                        if line.lower()[0] != '^':
                            self.widget_pager.buffer([line])
                            self.display()
                        line = ""
        except:
            child.close()
        self.value = child.exitstatus
        if self.pause:
            what_to_display = "Нажмите Enter для продолжения..."
            self.widget_pager.buffer([" "])
            self.widget_pager.buffer([what_to_display])
            self.widget_pager.handlers = {curses.ascii.NL: self.exit_form}
        else:
            what_to_display = "Выполнение завершено..."
            self.widget_pager.buffer([" "])
            self.widget_pager.buffer([what_to_display])
            self.while_editing=self.exit_form

    def exit_form(self, *args):
        self.editing = False
        self.exit_editing()


def frame_system_call(command, pause=True):
    frame_system_call_form = Frame_System_Call(command, pause)
    frame_system_call_form.edit()
    return frame_system_call_form.value

def system_call(command):
    bash_script = ["bash", "-c"]
    bash_script.append(command)
    p = subprocess.run(bash_script, capture_output=True, text=True)
    return p.stdout

def truncate_string(string, length):
    truncated_string = string[:length] + (len(string) < length) * (length - len(string)) * " "
    return truncated_string


def split_string(string, length):
    #return [string[i:i+length] for i in range (0, len(string), length)]
    line = ""
    array = []
    for word in string.split():
        if len(line) + len(word) > length:
            array.append(line)
            line = ""
        line = str(line) + " " + str(word)
    array.append(line)
    return array

def get_astra_version():
    try:
        f = open('/etc/astra_version','r')
        astra_version=f.read()
    except:
        return None
    finally:
        f.close()
    return  astra_version[:-1]

def get_astra_build():
    try:
        f = open('/etc/astra/build_version','r')
        astra_version=f.read()
    except:
        return None
    finally:
        f.close()
    return  astra_version[:-1]

def astra_modeswitch(mode):
    system_call(f"astra-modeswitch set {mode}")

def update_hostname(hostname, domainname):
    system_call(f"hostnamectl set-hostname {hostname}.{domainname}")
    with open("/etc/hostname", "w") as hostname_file:
        print(f"{hostname}.{domainname}", file=hostname_file)

def update_resolv_conf(domainname, dns1, dns2=""):
    with open("/etc/resolv.conf", "w") as hostname_file:
        print(f"domain {domainname}", file=hostname_file)
        print(f"search {domainname}", file=hostname_file)
        print(f"nameserver {dns1}", file=hostname_file)
        if dns2 != "":
            print(f"nameserver {dns2}", file=hostname_file)

def update_hosts(hostname, domainname, ip):
    with open("/etc/hosts", "r") as hosts_file:
        origin_hosts_file = hosts_file.readlines()

    tmp_hosts_file = []
    for index, line in enumerate(origin_hosts_file):
        line = str(line)
        if "127.0.0.1" in line:
            pass
        elif "127.0.1.1" in line:
            pass
        elif hostname in line:
            pass
        elif str(ip) in line:
            pass
        elif line.replace("\t", "").replace(" ", "").replace("\n", "") == "":
            pass
        else:
            tmp_hosts_file.append(line)

    with open("/etc/hosts", "w") as hosts_file:
        print(f"127.0.0.1\tlocalhost.localdomain\tlocalhost", file=hosts_file)
        print(f"127.0.1.1\t{hostname}", file=hosts_file)
        print(f"{ip}\t{hostname}.{domainname}\t{hostname}", file=hosts_file)
        for line in tmp_hosts_file:
            print(line, file=hosts_file)

def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(0)
    try:
        s.connect(("8.8.8.8",1))
        ip = s.getsockname()[0]
    except:
        ip = "127.0.0.1"
    finally:
        s.close()
    return ip